iT邦幫忙

2026 iThome 鐵人賽

DAY 30
0
Software Development

程式設計沒有告訴你的事:30 天破解每一個 Why系列 第 30

從「我只會用 Framework」到「我知道 Framework 為什麼存在」:30 天最終成果

  • 分享至 

  • xImage
  •  

Day1 的時候,我問自己的問題其實不是:

我要怎麼做一個 Web Framework?

而是:

為什麼我學了這麼多程式,遇到真正的問題時,還是常常不知道程式到底怎麼運作?

以前學程式時,我很容易記住:

這段程式怎麼寫。

這個 API 怎麼呼叫。

這個 Framework 要怎麼用。

但如果再多問一句:

為什麼?

我就常常回答不出來。

為什麼 CPU 看不懂 C#?

為什麼 Build 之後會產生 DLL?

為什麼 Server 可以一直等待 Request?

為什麼 Browser 輸入網址之後,Server 就知道我要去哪裡?

為什麼只寫 return "Hello" 就可以讓 Browser 收到 Response?

為什麼 ASP.NET Core 可以自動把 JSON 變成 C# Object?

為什麼 Handler 的參數不用自己一個一個從 Request 裡拿?

這些原本看起來完全不同的問題,最後竟然全部接到了一起。

所以來到 Day30,最後真正想回答的問題是:

這 30 天,我到底理解了什麼?

以及:

我真的做出了什麼?

💭 回到 Day1 的我

一開始,我對 Framework 的理解其實很簡單。

Framework 就是一個:

幫我把很多東西做好了的工具。

例如 ASP.NET Core。

我知道可以建立 Controller。

知道可以設定 Route。

知道可以 return JSON。

知道可以使用 Request。

但我不知道:

Request 從哪裡來?

Route 為什麼會找到 Controller?

return 的東西最後怎麼回到 Browser?

Framework 到底替我做了多少事情?

所以以前使用 Framework 時,很多東西對我來說都很像:

魔法。

輸入:

app.MapGet(...)

然後它就可以工作。

但這 30 天做的事情,就是把這些「魔法」一層一層拆開。

第一段旅程:C# 到底怎麼跑起來?

最開始,我甚至沒有直接碰 HTTP。

而是從一個更底層的問題開始:

CPU 看得懂 C# 嗎?

答案當然是不行。

所以一路追下去:

C# Source Code

Compiler

IL

Assembly

CLR

JIT

Machine Code

CPU

以前只知道:

按下 Run

程式就執行。

現在至少開始知道,Run 中間其實跨過了很多層。

Day3 開始看 Compiler。

Day4 開始拆 Build。

Day5 看 Build 後為什麼產生這麼多檔案。

Day6 第一次用 ILDasm 打開自己的 DLL。

Day7 看 C# 改變之後 IL 真的也跟著改變。

這幾天最重要的不是背:

ldstr

call

ret

而是第一次真正看到:

我寫的 C# 並不是 CPU 最後直接執行的東西。

中間存在很多轉換。

這個觀念後來其實一直重複出現在 Framework 裡。

高階程式碼

底層形式

Framework 的工作也常常是在做類似的事情。

第二段旅程:程式為什麼可以變成 Server?

接著開始研究:

為什麼一般程式跑完就結束,

Web Server 卻可以一直等待 Request?

一開始只用:

while(true)

證明程式可以不結束。

接著又用:

Console.ReadLine()

理解「等待」和「一直忙碌執行」不是完全一樣的事情。

然後第一次真正接觸:

TcpListener

TcpClient

NetworkStream

那時候才開始理解:

Web Server 並不是一個特別神祕的程式。

它也是一個正在執行的 Process。

只是在某個 Port 上等待 Client Connection。

所以:

Browser

TCP Connection

Server

這條線第一次出現。

第三段旅程:Browser 到底傳了什麼?

第一次真的用 Browser 連自己的 Server 時,我看到了:

GET / HTTP/1.1

Host: ...

User-Agent: ...

Accept: ...

以前一直說:

Browser 會傳 Request。

但直到自己把原始資料印出來,才真正知道 Request 長什麼樣。

後來把網址改成:

/hello

真的看到:

GET /hello HTTP/1.1

這件事情其實非常簡單。

但它讓我第一次知道:

Browser 裡的網址 Path,最後真的會出現在 HTTP Request 裡。

接著開始拆:

Method

Path

Version

Headers

Query

Body

原本只有一大串 HTTP Text,

最後慢慢變成:

HttpRequest
├── Method
├── Path
├── Version
├── Headers
├── Query
└── Body

這讓我第一次理解:

HttpRequest 並不是 Browser 傳來的一個 C# Object。

它是 Framework 根據 HTTP Data 建立出來的抽象。

第四段旅程:Routing 原來沒有那麼神祕

以前使用 Framework:

/hello

Hello Handler

會覺得 Routing 好像是一個很複雜的功能。

但真正從零開始做時,第一版其實只是:

if path == "/hello"

然後:

if / else

慢慢變成:

Dictionary

接著變成:

Route Table

最後:

Path

找到 Handler

執行 Handler

這時才真正理解 Routing 的核心:

Matching

Dispatching

也就是:

Request 要交給誰?

真正 Framework 的 Routing 當然比我們的 Dictionary 複雜很多。

但核心問題其實沒有改變。

第五段旅程:Handler 執行完之後呢?

找到 Handler 後,最開始只是:

Console.WriteLine()

結果只出現在 Server Console。

Browser 根本看不到。

所以開始研究:

HTTP Response。

第一次自己手動建立:

HTTP/1.1 200 OK

Content-Type

Content-Length

空白行

Body

再把 Response:

string

Encoding

bytes

NetworkStream.Write()

送回 Browser。

當 Browser 第一次真的顯示:

Hello!

那個瞬間其實很重要。

因為整個流程第一次完整閉環:

Browser

Request

Server

Handler

Response

Browser

接著又做:

404 Not Found

才開始理解 Status Code 不只是我們平常看到的一個數字。

它真的存在 HTTP Response 中。

第六段旅程:為什麼需要 HttpRequest 和 HttpResponse?

做到 Request 和 Response 都能工作後,新的問題開始變成:

程式可以跑。

但為什麼越來越亂?

Program.cs 同時知道:

TCP

HTTP

Parsing

Routing

Response

Encoding

NetworkStream

所有事情。

於是第一次建立:

HttpResponse

把:

StatusCode

ContentType

Body

Send()

集中起來。

接著又想到:

Response 都變成 Object 了。

Request 為什麼還是一堆:

string

Split

parts[0]

parts[1]

所以又開始設計:

HttpRequest。

這時我第一次真的理解:

Object 的價值不只是把幾個變數包在一起。

更重要的是:

建立一個其他程式可以依賴的介面。

例如:

parts[1]

和:

request.Path

最後可能都是:

/products

但它們代表完全不同的設計。

第七段旅程:Framework 為什麼可以這麼「自動」?

接著問題一路往更高層走。

Query String:

?name=Andy

怎麼變成:

Query["name"]

Request Body:

JSON

怎麼變成:

C# Object

Handler:

CreateUser(User user)

Framework 又怎麼知道:

它需要 User?

這時開始碰到:

Serialization

Deserialization

Reflection

Metadata

Parameter Binding

以前看到:

User user

會覺得 Framework 就是自動把資料放進來。

現在至少可以拆成:

Handler

Reflection

發現 Parameter Type = User

Request

Body

JSON

兩邊接起來:

JSON

Deserialize()

User Object

Handler Parameter

所以「自動」不是沒有規則。

只是 Framework 幫我們把規則包起來了。

第八段旅程:Middleware 和 Pipeline

最後又出現:

Logging

Authentication

Exception Handling

這些每個 Request 都可能需要的功能。

難道每個 Handler 都自己寫?

於是開始理解:

Middleware。

Request

Middleware A

Middleware B

Handler

Middleware B

Middleware A

Response

以及:

next()

代表:

把控制權交給後面的 Pipeline。

這時才開始理解:

Framework 不只是在管理資料。

它也在管理:

程式的執行流程。

最後所有東西串起來後:

Browser

TCP

HttpRequest

Middleware Pipeline

Routing

Parameter Binding

Handler

Result Conversion

HttpResponse

TCP

Browser

這就是這 30 天最後慢慢拼出的圖。

我最後做出了什麼?

這次專案叫:

Mini Web Framework

它當然不是 ASP.NET Core。

也不是一個可以拿去正式部署大型網站的 Production Framework。

官方文件和自己的 Framework 有什麼差別?

這 30 天大量查 Microsoft 官方文件後,我最大的感受是:

以前看官方文件時,

常常只是在找:

這個 API 怎麼用?

但自己拆過一次 Framework 後,再看到:

HttpRequest

HttpResponse

Routing

Middleware

Reflection

Model Binding

這些名詞,

開始不只是記:

怎麼使用。

而是會想到:

它為什麼需要存在?

例如看到 HttpRequest,

會想到:

Browser 傳來的其實是 HTTP Data。

看到 Routing,

會想到:

Request Path 必須被 Match 到 Handler。

看到 Middleware,

會想到:

Pipeline 和 Delegate。

看到 Model Binding,

會想到:

Reflection + Request Data + Type Conversion。

所以官方文件好像也沒有以前那麼「魔法」了。

🧠 30 天最大的認知更新

Day1:

我想知道 Framework 怎麼用。

Day30:

我開始知道 Framework 為什麼存在。

以前:

return "Hello";

現在看到的是:

Handler Result

Framework

HttpResponse

HTTP

bytes

TCP

Browser

以前:

Request.Path

現在看到的是:

TCP bytes

HTTP Parsing

Request Target

Path

HttpRequest.Path

以前:

app.MapGet()

現在看到的是:

Route Registration

Route Table

Request

Matching

Handler

以前:

User user

現在看到的是:

Handler Metadata

Reflection

Parameter Type
+
Request Body

JSON

Deserialization

Parameter Binding

User

這就是這 30 天最大的差別。

不是多背了多少 API。

而是看到 API 後,

開始有能力往下問:

Why?


如果要選一個最大的發現,

我覺得不是:

TCP

不是:

Routing

不是:

Reflection

也不是:

Middleware。

而是:

抽象沒有讓底層消失。

它只是把底層複雜度藏到更適合的位置。

我們寫:

request.Path

不代表 HTTP Parsing 不存在。

我們寫:

return user

不代表 Serialization 不存在。

我們寫:

MapGet

不代表 Routing 不存在。

我們使用 Framework,

並不是底層突然不需要了。

只是 Framework 替我們承擔那些細節。

所以:

Framework 的價值不是「魔法」。

而是:

管理複雜度。

這是這 30 天對我來說最重要的一個答案。


上一篇
Framework 組好了,但真的能用嗎?開始做完整整合測試
系列文
程式設計沒有告訴你的事:30 天破解每一個 Why30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言